package org.infinitest.swingui;

import static org.infinitest.InfinitestPresenter.*;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;

import javax.swing.Action;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.Timer;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.tree.TreeModel;

import org.infinitest.ResultCollector;

public class InfinitestMainFrame extends JFrame implements InfinitestView
{
  private static final int RESIZE_WINDOW_HANDLE_WIDTH = 13;
  private static final String APP_TITLE = "Infinitest";
  private JToolBar toolbar;
  private ColorAnimator animator;
  private CustomProgressBar progressBar;
  private JTree tree;
  private Color color;

  InfinitestMainFrame()
  {
    URL iconURL = InfinitestMainFrame.class.getResource("infinitest-icon.png");
    setIconImage(new ImageIcon(iconURL).getImage());
    setAlwaysOnTop(true);
    setLayout(new BorderLayout());
    addWindowListener(new WindowBoundsManager());
    toolbar = createToolBar();
    animator = new ColorAnimator();
    progressBar = createProgressbar(animator);
    tree = createTree();
    setBounds(WindowBoundsManager.getWindowBounds());
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel southComponent = new JPanel(new BorderLayout());
    if (UIManager.getSystemLookAndFeelClassName().equals("apple.laf.AquaLookAndFeel"))
    {
      southComponent.add(Box.createHorizontalStrut(RESIZE_WINDOW_HANDLE_WIDTH), BorderLayout.EAST);
    }
    southComponent.add(progressBar, BorderLayout.CENTER);
    southComponent.add(toolbar, BorderLayout.WEST);
    add(southComponent, BorderLayout.SOUTH);
    add(new JScrollPane(tree), BorderLayout.CENTER);
    addWindowFocusListener(new TreeFocusListener());
  }

  private static JToolBar createToolBar()
  {
    JToolBar toolbar = new JToolBar(JToolBar.HORIZONTAL);
    toolbar.setName("TOOLBAR");
    return toolbar;
  }

  private static JTree createTree()
  {
    JTree resultsTree = new JTree();
    resultsTree.setName("TREEVIEW");
    resultsTree.setRootVisible(false);
    resultsTree.setEditable(false);
    resultsTree.setShowsRootHandles(true);
    resultsTree.setCellRenderer(new FailureCellRenderer());
    ToolTipManager tipManager = ToolTipManager.sharedInstance();
    tipManager.registerComponent(resultsTree);
    resultsTree.addMouseListener(new ResultClickListener());
    resultsTree.addKeyListener(new EnterPressListener());
    return resultsTree;
  }

  private CustomProgressBar createProgressbar(final ColorAnimator animator)
  {
    final CustomProgressBar progressBar = new CustomProgressBar();
    progressBar.setName("PROGRESSBAR");
    color = getUnknownColor();
    Timer timer = new Timer(animator.getAnimationRate(), new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        progressBar.setForeground(animator.shiftColorOnAnimationTick(color));
        progressBar.repaint();
        animator.tick();
      }
    });
    timer.start();
    return progressBar;
  }

  private JProgressBar getProgressBar()
  {
    return progressBar;
  }

  private JToolBar getToolbar()
  {
    return toolbar;
  }

  public JTree getTree()
  {
    return tree;
  }

  public void setAngerBasedOnTime(long timeSinceGreen)
  {
    animator.setAngerBasedOnTime(timeSinceGreen);
  }

  public int getAngerLevel()
  {
    return animator.getAngerLevel();
  }

  public void setAngerLevel(int anger)
  {
    animator.setAngerLevel(anger);
  }

  public void setProgressBarColor(Color progressBarColor)
  {
    color = progressBarColor;
  }

  public void setProgress(int progress)
  {
    getProgressBar().setValue(progress);
  }

  public void setMaximumProgress(int maxProgress)
  {
    getProgressBar().setMaximum(maxProgress);
  }

  public int getMaximumProgress()
  {
    return getProgressBar().getMaximum();
  }

  public int getProgress()
  {
    return getProgressBar().getValue();
  }

  public void setCurrentTest(String testName)
  {
    progressBar.setCurrentTest(testName);
  }

  public void setCycleTime(String timeStamp)
  {
    setTitle(APP_TITLE + " - Cycle Time: " + timeStamp);
  }

  public void addAction(Action action)
  {
    getToolbar().add(action);
  }

  public void setResultsModel(TreeModel results)
  {
    getTree().setModel(results);
    TreeModelExpansionListener.watchTree(getTree());
  }

  public Color getProgressBarColor()
  {
    return color;
  }

  public static InfinitestView createFrame(ResultCollector results)
  {
    InfinitestMainFrame mainFrame = new InfinitestMainFrame();
    mainFrame.setResultsModel(new TreeModelAdapter(results));
    return mainFrame;
  }

  public void setStatusMessage(String statusMessage)
  {
    progressBar.setStatusMessage(statusMessage);
  }
}
